<template>
  <div>
    <BasicModal
      @register="registerModal"
      title="扫码编箱"
      width="50%"
      okText="确认编箱"
      :closable="false"
    >
      <Spin :spinning="spinning">
        <BasicTable @register="registerTable">
          <template #bodyCell="{ column, index }">
            <template v-if="column.key === 'waterMeterCode'">
              <Input
                allowClear
                :ref="(el) => waterCodeRef(el, index)"
                @change="(e) => changeInput(e, index)"
                v-model:value="list[index][column.key]"
                @blur="changeBlur"
                @focus="changeFocus"
              />
            </template>
            <template v-if="column.key === 'certificateCode'">
              <Input
                @blur="changeBlur"
                @focus="changeFocus"
                allowClear
                :ref="(el) => certCodeRef(el, index)"
                @change="(e) => changeCert(e, index)"
                v-model:value="list[index][column.key]"
              />
            </template>
          </template>
        </BasicTable>
      </Spin>
      <template #footer>
        <div>
          <Button @click="handleClearAll">一键清除</Button>
          <Button @click="handleStart">扫合格证</Button>
          <Button @click="handleClose">取消编箱</Button>
          <Button type="primary" @click="handleSubmit">确认编箱</Button>
        </div>
      </template>
    </BasicModal>
    <qrcodeHtml
      :qrCodeData="qrCodeData"
      :modalInfoList="modalInfoList"
      class="qrcode-hidden"
      id="qrcode-01"
    />
  </div>
</template>

<script setup lang="ts">
  import { ref, nextTick } from 'vue';
  import { Spin, Input, Modal, Button } from 'ant-design-vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicTable, useTable } from '/@/components/Table';
  import qrcodeHtml from './qrcode-html.vue';
  import { QrBoxSchemas } from '../index.data';
  import {
    getCodeEncasementNum,
    getTaskEncasement,
    submitReduceCodeHandle,
    getBoxQrCodeMsg,
  } from '/@/api/jd/water-box';
  import { ListItem } from '/@/api/jd/model/water-box';
  import { CommonParam } from '../types';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { isArray, isBoolean } from '/@/utils/is';
  import { printHtml } from '../hooks/printjs';

  const $emit = defineEmits(['success', 'register']);

  interface PropsParams {
    task_id?: string;
    apply_id?: string;
    [key: string]: any;
  }

  interface InstanceItem {
    el: any;
    id: number;
  }

  interface RowColItem {
    row: number;
    col: number;
  }

  const props = withDefaults(
    defineProps<{
      record: PropsParams;
    }>(),
    { record: () => ({}) },
  );

  const { createMessage } = useMessage();

  const spinning = ref(true);
  let waterCodeList: InstanceItem[] = [];
  let certCodeList: InstanceItem[] = [];
  const list = ref<ListItem[]>([]);
  const [registerTable, { setTableData }] = useTable({
    columns: QrBoxSchemas,
    pagination: false,
  });

  let taskId: any = null;

  const qrCodeData = ref<any>({});

  const modalInfoList = ref<CommonParam[]>([]);

  const [registerModal, { closeModal }] = useModalInner(async (data) => {
    taskId = data.task_id;

    const ret = await getCodeEncasementNum(taskId);
    spinning.value = false;

    for (let i = 0; i < ret; i++) {
      list.value.push({
        waterMeterCode: '',
        certificateCode: '',
      });
    }
    setTableData(list.value);
  });

  // 获取二维码数据
  const getQrcodeData = async (boxId) => {
    qrCodeData.value = await getBoxQrCodeMsg(boxId);
    modalInfoList.value = [
      { title: '箱号', value: qrCodeData.value.boxCode },
      // { title: '检定员', value: qrCodeData.value.userName },
      { title: '编箱日期', value: qrCodeData.value.buildBoxTime },
      { title: '水表口径', value: qrCodeData.value.caliber },
      // { title: '本批次数量', value: qrCodeData.value.totalNumber },
      { title: '一箱数量', value: qrCodeData.value.boxNumber },
    ];

    nextTick(() => {
      printHtml('qrcode-01');
    });
  };

  // 获取表码输入框实例
  const waterCodeRef = (el, key) => {
    nextTick(() => {
      if (el) {
        const waterItemList = waterCodeList.map((i) => i.id);
        if (!waterItemList.includes(key)) {
          if (key === 0) {
            el.focus();
          }
          waterCodeList.push({
            el: el,
            id: key,
          });
        }
      }
    });
  };

  // 获取合格证编码输入框实例
  const certCodeRef = (el, key) => {
    nextTick(() => {
      if (el) {
        const certItemList = certCodeList.map((i) => i.id);
        if (!certItemList.includes(key)) {
          if (key === 0) {
            el.focus();
          }
          certCodeList.push({
            el: el,
            id: key,
          });
        }
      }
    });
  };

  // 校验必填
  const validate = (data: ListItem[]): boolean | RowColItem[] => {
    if (!isArray(data)) return false;
    const arr: RowColItem[] = [];
    data.forEach((i, x) => {
      let obj: RowColItem = {
        row: -1,
        col: -1,
      };
      if (!i.waterMeterCode && i.certificateCode) {
        obj.row = x;
        obj.col = 0;
        arr.push(obj);
      }
      if (i.waterMeterCode && !i.certificateCode) {
        obj.row = x;
        obj.col = 1;
        arr.push(obj);
      }
    });
    return arr;
  };

  // 确定
  const handleSubmit = async () => {
    const validateRet = validate(list.value);

    if (isBoolean(validateRet)) {
      createMessage.warn('校验参数不合法，传入的校验数据不是数组！');
      return;
    }

    if (isArray(validateRet) && validateRet.length) {
      let str = '';
      (validateRet as RowColItem[]).forEach((i, x) => {
        if (x === validateRet.length - 1) {
          str += `第${i.row + 1}行${i.col + 1}列、数据请补充完整！`;
        } else {
          str += `第${i.row + 1}行${i.col + 1}列、`;
        }
      });

      createMessage.warn(str);
      return;
    }

    const { code, msg, type, boxId } = await getTaskEncasement({
      taskId,
      waterMeterCodes: list.value.filter((i) => i.waterMeterCode && i.certificateCode),
    });

    if (type === 0) {
      // createMessage.success('操作成功');
      printQrcode(boxId?.[0]);
    }

    if (type === 1) {
      createMessage.warn(msg);
      return;
    }

    if (type === 2) {
      Modal.confirm({
        title: '表码插入',
        content: msg,
        onOk: async () => {
          await submitReduceCodeHandle({
            taskId: props.record?.task_id as string,
            applyId: props.record?.apply_id as string,
            waterMeterCodes: code,
          });
          $emit('success');
          handleClearAll();
          // handleClose();
        },
        onCancel: () => {},
      });
      return;
    }

    $emit('success');
    handleClearAll();
    // handleClose();
  };
  // 提取url参数
  function getUrlParams(url) {
    // 通过 ? 分割获取后面的参数字符串
    let urlStr = url.split('?')[1];
    // 创建空对象存储参数
    let obj = {};
    // 再通过 & 将每一个参数单独分割出来
    let paramsArr = urlStr.split('&');
    for (let i = 0, len = paramsArr.length; i < len; i++) {
      // 再通过 = 将每一个参数分割为 key:value 的形式
      let arr = paramsArr[i].split('=');
      obj[arr[0]] = arr[1];
    }
    return obj;
  }

  // 打印二维码
  const printQrcode = (boxId) => {
    Modal.confirm({
      title: '二维码打印',
      content: '是否打印二维码',
      onOk: async () => {
        getQrcodeData(boxId);
      },
      onCancel: () => {},
    });
  };

  const handleClose = () => {
    Modal.confirm({
      title: '取消编箱',
      content: '关闭编箱页面后当前录入数据将会清除，是否关闭',
      onOk: () => {
        list.value = [];
        waterCodeList = [];
        certCodeList = [];
        closeModal();
      },
      onCancel: () => {},
    });
  };
  let str = '';
  let timer: any = null;
  let changeTimer: any = null;
  let certTimer: any = null;

  // 赋值粘贴处理
  const copyToPasteFormat = (str: string, field, index) => {
    if (!str || str.indexOf(' ') === -1) return;
    const dataList = str.split(' ');
    dataList.forEach((i, x) => {
      list.value[x + index][field] = i;
    });
  };

  // 表码输入处理
  const changeInput = (e, index) => {
    timer && clearTimeout(timer);
    timer = null;
    if (e) {
      str = e.target.value;
    }
    timer = setTimeout(() => {
      if (!str || str.indexOf('?') === -1 || str.indexOf('&') === -1) {
        copyToPasteFormat(str, 'waterMeterCode', index);
      } else {
        const param = getUrlParams(str);
        str = '';
        list.value[index].waterMeterCode = param.c;
        if (index + 1 < waterCodeList.length) {
          const lastWaterItem = waterCodeList.find((i) => index + 1 === i.id);
          if (lastWaterItem) {
            lastWaterItem.el.focus();
          }
        }
      }
    }, 100);
  };

  //合格证编码处理
  const changeCert = (e, index) => {
    certTimer && clearTimeout(certTimer);
    certTimer = null;
    if (e) {
      str = e.target.value;
    }
    certTimer = setTimeout(() => {
      if (!str || str.indexOf('?') === -1 || str.indexOf('&') === -1) {
        copyToPasteFormat(str, 'certificateCode', index);
      } else {
        const param = getUrlParams(str);
        str = '';
        list.value[index].certificateCode = param.c;
        if (index + 1 < certCodeList.length) {
          const lastCertItem = certCodeList.find((i) => index + 1 === i.id);

          if (lastCertItem) {
            lastCertItem.el.focus();
          }
        }
      }
    }, 100);
  };

  // 一键清除
  const handleClearAll = () => {
    list.value.forEach((i) => {
      i.waterMeterCode = '';
      i.certificateCode = '';
    });
    handleStart();
  };

  // 开始编箱
  const handleStart = () => {
    if (certCodeList.length) {
      certCodeList[0].el.focus();
    }
  };

  const changeBlur = () => {
    console.log('%c失焦', 'color:#f78;font-size:30px;font-weight:bold');
    changeTimer = setTimeout(() => {
      handleAtuoFocus();
    }, 500);
  };
  const changeFocus = () => {
    console.log('%c聚焦', 'color:#f78;font-size:30px;font-weight:bold');
    changeTimer && clearTimeout(changeTimer);
    changeTimer = null;
  };

  // 失焦后自动聚焦
  const handleAtuoFocus = () => {
    try {
      list.value.forEach((i, x) => {
        if (!i.waterMeterCode) {
          waterCodeList[x].el.focus();
          throw false;
        }
        if (!i.certificateCode) {
          certCodeList[x].el.focus();
          throw false;
        }
      });
    } catch (e) {}
  };
</script>

<style lang="less" scoped>
  .qrcode-hidden {
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;
  }

  .ant-input-affix-wrapper:focus,
  .ant-input-affix-wrapper-focused {
    border-color: #f00;
    box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.18);
  }

  .ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover {
    border-color: #f00;
  }
</style>
